package com.guigu.commons.config;

import com.guigu.commons.filter.TokenAuthenticationFilter;
import com.guigu.commons.filter.TokenLoginFilter;
import com.guigu.commons.handler.AxiosAccessDeniedHandler;
import com.guigu.commons.security.TokenLogoutHandler;
import com.guigu.commons.security.UnAuthorizedPoint;
import com.guigu.commons.utils.JwtUtils;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

/**
 * @ClassName:SpringSecurityConfig
 * @Description:security配置类
 * @Author:longtao
 * @Date:2021/6/28
 * @Version:1.0
 */
@Configuration
//开启springSecurity注解
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true, jsr250Enabled = true)
@EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
    private JwtUtils jwtUtils;
    private UserDetailsService userDetailsService;
    private RedisTemplate redisTemplate;

    public SpringSecurityConfig(JwtUtils jwtUtils, UserDetailsService userDetailsService, RedisTemplate redisTemplate) {
        this.jwtUtils = jwtUtils;
        this.userDetailsService = userDetailsService;
        this.redisTemplate = redisTemplate;
    }

    @Bean
    public BCryptPasswordEncoder bcryptPasswordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.exceptionHandling()
                .authenticationEntryPoint(new UnAuthorizedPoint())//匿名用户无权限获取资源时
                .and().csrf().disable()//禁用csrf
                //.cors().configurationSource(CorsConfigurationSource())//配置跨域
                //.and()
                .authorizeRequests()//授权请求配置
                //  .anyRequest().access("")
                //.antMatchers("user/login","auth/auth-user/findByToken","v2/api-docs").permitAll()
                .anyRequest().authenticated()//其他资源都需要认证才能访问
                .and().logout().logoutUrl("/user/logout")//退出路径
                .addLogoutHandler(new TokenLogoutHandler(redisTemplate)).and()//配置注销处理类
                .addFilter(new TokenLoginFilter(authenticationManager()))//配置认证过滤器
                .addFilter(new TokenAuthenticationFilter(authenticationManager(), jwtUtils))//配置授权过滤器
                .httpBasic()
                .and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);//永远不配置session话
        http.exceptionHandling().accessDeniedHandler(new AxiosAccessDeniedHandler());//无权访问
//        http.authorizeRequests().anyRequest().permitAll().and().csrf().disable();
    }


    /**
     * 将userDetailsService和bcryptPasswordEncoder放在auth中
     *
     * @param auth
     * @throws Exception
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(bcryptPasswordEncoder());
    }

    //不进行认证的路径,可以直接访问
    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers(
                "user/login",
                "/auth/auth-user/findByToken",
                "/v2/api-docs",
                "/auth/auth-resource/queryResourcesBasedOnUserId/*",
                "/auth/auth-resource/queryAll",
                "/api/ucenter/wx/**",
                "/error/**");//不进行授权,都可以访问
    }


/*    private CorsConfigurationSource CorsConfigurationSource() {
        CorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.addAllowedOrigin("*");    //同源配置，*表示任何请求都视为同源，若需指定ip和端口可以改为如“localhost：8080”，多个以“，”分隔；
        corsConfiguration.addAllowedHeader("*");//header，允许哪些header，本案中使用的是token，此处可将*替换为token；
        corsConfiguration.addAllowedMethod("*");    //允许的请求方法，PSOT、GET等
        ((UrlBasedCorsConfigurationSource) source).registerCorsConfiguration("/**", corsConfiguration); //配置允许跨域访问的url
        return source;
    }*/

    @Bean
    @Override
    protected AuthenticationManager authenticationManager() throws Exception {
        return super.authenticationManager();
    }
}
